﻿namespace EFS.RC.CCC.Channels.Contexts.Operators
{
	/// <summary>
	/// supervisor context channel
	/// </summary>
	internal class Agent : EFS.RC.Common.AsyncRoot
	{
		// collaboration channel
		private Microsoft.Rtc.Collaboration.ConversationContextChannel conversationContextChannel;
		
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="conversation"></param>
		/// <param name="remoteEndpoint"></param>
		public Agent(Microsoft.Rtc.Collaboration.Conversation conversation, Microsoft.Rtc.Collaboration.ParticipantEndpoint remoteEndpoint)
		{
			// check
			EFS.Common.Verify.Reference(conversation, "conversation");
			EFS.Common.Verify.Reference(remoteEndpoint, "remoteEndpoint");

			// make new
			conversationContextChannel = new Microsoft.Rtc.Collaboration.ConversationContextChannel(conversation, remoteEndpoint);

			// log
			EFS.EventLog.Log.LogInfo("SupervisorContext", this);
		}

		/// <summary>
		/// Describe this object into a nice formated string
		/// </summary>
		/// <returns></returns>
		public override System.String Describe()
		{
			return System.String.Format("EFS.RC.CCC.Channels.AudioVideo.Operators.SupervisorContext {0} {1}", conversationContextChannel.Conversation.Endpoint.OwnerUri, conversationContextChannel.RemoteEndpoint.Uri);
		}

		/// <summary>
		/// Begin platform startup
		/// </summary>
		public EFS.RC.Common.AsyncProcess BeginStartup()
		{
		    // log
		    EFS.EventLog.Log.LogInfo("BeginStartup", this);

		    // start end point
		    return BeginAsyncProcess(Startup, OnStartupComplete);
		}

		/// <summary>
		/// Send data message into the channel
		/// </summary>
		/// <param name="message"></param>
		/// <returns></returns>
		public System.IAsyncResult BeginDataSend(EFS.RC.CCC.Messages.Message message)
		{
			// check
			EFS.Common.Verify.Reference(message, "message");

			// begin send context data
			return conversationContextChannel.BeginSendData(
				new System.Net.Mime.ContentType(message.ContentType),
				message.SerializeToByteArray(),
				EndSendContextData, 
				null);
		}

		/// <summary>
		/// Begin platform startup
		/// </summary>
		public EFS.RC.Common.AsyncProcess BeginShutdown()
		{
		    // log
		    EFS.EventLog.Log.LogInfo("BeginStartup", this);

		    // start end point
		    return BeginAsyncProcess(Shutdown, OnShutdownComplete);
		}

		#region Startup

		/// <summary>
		/// Startup
		/// </summary>
		private void Startup()
		{
			// options
			Microsoft.Rtc.Collaboration.ConversationContextChannelEstablishOptions conversationContextChannelEstablishOptions = 
				new Microsoft.Rtc.Collaboration.ConversationContextChannelEstablishOptions();

			// set toast
			//conversationContextChannelEstablishOptions.Toast = "supervisor-channel";

			// data 
			conversationContextChannel.DataReceived += DataReceived;

			// begin
			conversationContextChannel.BeginEstablish(EFS.RC.CCC.Config.CollabotationPlatofrm.SupervisorCentralApplicationId, conversationContextChannelEstablishOptions, EndEstablisContextChannel, null);
		}

		/// <summary>
		/// Start-up complete
		/// </summary>
		/// <param name="ar"></param>
		private void OnStartupComplete(EFS.RC.Common.AsyncProcess ap)
		{
			// log
			EFS.EventLog.Log.LogInfo("OnStartupComplete", this);

			try
			{
				// check
				ap.Throw();

				// log
				EFS.EventLog.Log.LogInfo("OnStartupComplete SUCCCESS", this);
			}
			catch (System.Exception ex)
			{
				// log
				EFS.EventLog.Log.LogException(ex, this);
			}
		}

		/// <summary>
		/// End establish
		/// </summary>
		/// <param name="result"></param>
		public void EndEstablisContextChannel(System.IAsyncResult ar)
		{
			EFS.EventLog.Log.LogInfo("EndEstablisContextChannel", this);

			try
			{
				// try 
				conversationContextChannel.EndEstablish(ar);

				// 
			}
			catch (Microsoft.Rtc.Signaling.RealTimeException rtex)
			{
				EFS.EventLog.Log.LogException(rtex, this);
				
				// shut it down
				BeginShutdown();
			}
		}

		#endregion

		#region Runtime

		/// <summary>
		/// Data received on channel
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void DataReceived(object sender, Microsoft.Rtc.Collaboration.ConversationContextChannelDataReceivedEventArgs ea)
		{
			try
			{
			    if (ea.ContentDescription != null)
			    {
					// ea.ContentDescription.GetBody()
					// ProcessRequest();
			    }
			}
			catch (System.Exception ex)
			{
				// log
				EFS.EventLog.Log.LogException(ex, this);
			}
		}

		/// <summary>
		/// Process request
		/// </summary>
		/// <param name="supervisorChannelRequest"></param>
		private void ProcessSupervisorRequest(System.String supervisorChannelRequest)
		{
			// this will go up
		}

		/// <summary>
		/// End data send
		/// </summary>
		/// <param name="result"></param>
		internal void EndSendContextData(System.IAsyncResult result)
		{
			// log
			EFS.EventLog.Log.LogInfo("EndSendContextData", this);

			try
			{
				// check
				conversationContextChannel.EndSendData(result);

				// log
				EFS.EventLog.Log.LogInfo("EndSendContextData SUCCCESS", this);
			}
			catch (System.Exception ex)
			{
				// log
				EFS.EventLog.Log.LogException(ex, this);
			}
		}

		#endregion

		#region Shutdown

		/// <summary>
		/// Shut down
		/// </summary>
		public void Shutdown()
		{
			EFS.EventLog.Log.LogInfo("Shutdown", this);

			// terninate context channel
			conversationContextChannel.BeginTerminate(EndTerminateContextChannel, null);
		}

				/// <summary>
		/// Shut down complete
		/// </summary>
		/// <param name="ar"></param>
		private void OnShutdownComplete(EFS.RC.Common.AsyncProcess ap)
		{
			// log
			EFS.EventLog.Log.LogInfo("OnShutdownComplete", this);

			try
			{
				// check
				ap.Throw();

				// log
				EFS.EventLog.Log.LogInfo("OnShutdownComplete SUCCCESS", this);
			}
			catch (System.Exception ex)
			{
				// log
				EFS.EventLog.Log.LogException(ex, this);
			}
		}

		/// <summary>
		///  End terminate context channel
		/// </summary>
		/// <param name="result"></param>
		public void EndTerminateContextChannel(System.IAsyncResult ar)
		{
			EFS.EventLog.Log.LogInfo("EndTerminateContextChannel", this);
			
			try
			{
				// try 
				conversationContextChannel.EndTerminate(ar);
			}
			catch (Microsoft.Rtc.Signaling.RealTimeException rtex)
			{
				EFS.EventLog.Log.LogException(rtex, this);
			}
		}

		#endregion
	}
}
